import java.util.ArrayList;
import java.util.List;

/**
 * @author SongJun
 * @description N皇后(回溯)
 * @date 2021/9/8 14:26
 */
public class NQueen {
    public static void main(String[] args) {
        NQueen instance = new NQueen();
        List<List<String>> rst = instance.solveNQueens(7);
        System.out.println("总共有"+rst.size()+"种方案");
        for(List<String> item : rst){
            System.out.println("---------------");
            for(String s : item){
                System.out.println(s);
            }
        }
    }

    public List<List<String>> solveNQueens(int n) {
        List<List<String>> rst = new ArrayList<>();
        char[][] board = new char[n][n];
        for(int i=0; i<n; i++){
            for(int j=0; j<n; j++){
                board[i][j] = '.';
            }
        }
        setQueen(rst, board, 0);
        return rst;
    }
    public void setQueen(List<List<String>> rst, char[][] board, int row){
        //终结条件
        if(row >= board.length){
            List<String> item = new ArrayList<>(board.length);
            StringBuilder sb = new StringBuilder();
            for(char[] chars : board){
                for(char c : chars){
                    sb.append(c);
                }
                item.add(sb.toString());
                sb.setLength(0);
            }
            rst.add(item);
            return;
        }
        char[] chars = board[row];
        //选择列表
        for(int i=0; i<chars.length; i++){
            //排除不合法选择
            if(!isValid(board, row, i)){
                continue;
            }
            //做选择
            chars[i] = 'Q';
            //进入下一层决策树
            setQueen(rst, board, row+1);
            //撤销选择, 尝试下一个选择
            chars[i] = '.';
        }
    }

    boolean isValid(char[][] board, int row, int column){
        for(int i=row; i>=0; i--){
            if(board[i][column] == 'Q'){
                return false;
            }
        }
        for(int i=row-1, c=column-1; i>=0 && c>=0; i--, c--){
            if(board[i][c] == 'Q'){
                return false;
            }
        }
        for(int i=row-1, c=column+1; i>=0 && c>=0 && c<board.length; i--, c++){
            if(board[i][c] == 'Q'){
                return false;
            }
        }
        return true;
    }












//    List<List<String>> res = new ArrayList<>();
//    /* 输入棋盘的边长n，返回所有合法的放置 */
//    public List<List<String>> solveNQueens(int n) {
//        // "." 表示空，"Q"表示皇后，初始化棋盘
//        char[][] board = new char[n][n];
//        for (char[] c : board) {
//            Arrays.fill(c, '.');
//        }
//        backtrack(board, 0);
//        return res;
//    }
//
//    public void backtrack(char[][] board, int row) {
//        // 每一行都成功放置了皇后，记录结果
//        if (row == board.length) {
//            res.add(charToList(board));
//            return;
//        }
//
//        int n = board[row].length;
//        // 在当前行的每一列都可能放置皇后
//        for (int col = 0; col < n; col++) {
//            // 排除可以相互攻击的格子
//            if (!isValid(board, row, col)) {
//                continue;
//            }
//            // 做选择
//            board[row][col] = 'Q';
//            // 进入下一行放皇后
//            backtrack(board, row + 1);
//            // 撤销选择
//            board[row][col] = '.';
//        }
//    }
//
//    /* 判断是否可以在 board[row][col] 放置皇后 */
//    public boolean isValid(char[][] board, int row, int col) {
//        int n = board.length;
//        // 检查列是否有皇后冲突
//        for (int i = 0; i < n; i++) {
//            if (board[i][col] == 'Q') {
//                return false;
//            }
//        }
//
//        // 检查右上方是否有皇后冲突
//        for (int i = row - 1, j = col + 1; i >=0 && j < n; i--, j++) {
//            if (board[i][j] == 'Q') {
//                return false;
//            }
//        }
//
//        // 检查左上方是否有皇后冲突
//        for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
//            if (board[i][j] == 'Q') {
//                return false;
//            }
//        }
//        return true;
//    }
//
//    public List charToList(char[][] board) {
//        List<String> list = new ArrayList<>();
//
//        for (char[] c : board) {
//            list.add(String.copyValueOf(c));
//        }
//        return list;
//    }
}
